﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework;

namespace Brain.Rendering
{
    public class SpritebatchDrawer : IDrawer2D, IDisposable
    {
        public SpriteBatch SpriteBatch { get; protected set; }

        public SpriteSortMode SortMode { get; set; }

        public BlendState BlendState { get; set; }

        public SamplerState SamplerState { get; set; }
        public RasterizerState RasterizerState { get; set; }
        public DepthStencilState DepthStencilState { get; set; }

        public Effect Effect;

        public Matrix TransformMatrix;

        public Texture2D Blank;

        public SpritebatchDrawer()
        {
            Blank = new Texture2D(Engine.Instance.GraphicsDevice, 1, 1);
            Blank.SetData(new Color[] { Color.White } );

            TransformMatrix = Matrix.Identity;

            SortMode = SpriteSortMode.Deferred;
            BlendState = BlendState.AlphaBlend;

            SamplerState = SamplerState.LinearClamp;
            DepthStencilState = DepthStencilState.None;
            RasterizerState = RasterizerState.CullCounterClockwise;

            SpriteBatch = new SpriteBatch(Engine.Instance.GraphicsDevice);
        }
        public void Dispose()
        {
            if (this.Effect != null &&
                !this.Effect.IsDisposed)
            {
                this.Effect.Dispose();
            }

            if (!SpriteBatch.IsDisposed)
            {
                SpriteBatch.Dispose();
            }
        }

        public void Begin()
        {
            SpriteBatch.Begin(SortMode, BlendState, SamplerState, DepthStencilState, RasterizerState, Effect, TransformMatrix);
        }

        public void End()
        {
            SpriteBatch.End();
        }

        public void Draw(Texture2D texture, Rectangle destinationRectangle, Color color)
        {
            SpriteBatch.Draw(texture, destinationRectangle, color);
        }

        public void Draw(Texture2D texture, Vector2 position, Color color)
        {
            SpriteBatch.Draw(texture, position, color);
        }

        public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color)
        {
            SpriteBatch.Draw(texture, destinationRectangle, sourceRectangle, color);
        }

        public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color)
        {
            SpriteBatch.Draw(texture, position, sourceRectangle, color);
        }

        public void Draw(Texture2D texture, Rectangle destinationRectangle, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.Draw(texture, destinationRectangle, sourceRectangle, color, rotation, origin, effects, layerDepth);
        }

        public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.Draw(texture, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
        }

        public void Draw(Texture2D texture, Vector2 position, Rectangle? sourceRectangle, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.Draw(texture, position, sourceRectangle, color, rotation, origin, scale, effects, layerDepth);
        }

        public void DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color);
        }

        public void DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color);
        }

        public void DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin, scale, effects, layerDepth);
        }

        public void DrawString(SpriteFont spriteFont, string text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin, scale, effects, layerDepth);
        }

        public void DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, float scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin, scale, effects, layerDepth);
        }

        public void DrawString(SpriteFont spriteFont, StringBuilder text, Vector2 position, Color color, float rotation, Vector2 origin, Vector2 scale, SpriteEffects effects, float layerDepth)
        {
            SpriteBatch.DrawString(spriteFont, text, position, color, rotation, origin, scale, effects, layerDepth);
        }

        public void DrawRectangle(Rectangle rectangle, Color color)
        {
            Draw(Blank, rectangle, color);
        }

        public void DrawRectangle(Rectangle rectangle, Color color, float rotation)
        {
            Draw(Blank, rectangle, null, color, rotation, Vector2.Zero, SpriteEffects.None, 0);
        }

        public void DrawLine(Vector2 start, Vector2 end, Color color)
        {
            float X = end.X - start.X;
            float Y = end.Y - start.Y;
            float Hyp = MathUtil.Hypotenuse(X, Y);

            Vector2 direction = new Vector2(X, Y);
            if (direction != Vector2.Zero)
            {
                direction.Normalize();
            }

            Rectangle rect = new Rectangle((int)start.X, (int)start.Y, (int)Hyp, 1);
            float ang = Vector2Util.Angle(direction);

            DrawRectangle(rect, color, ang);
        }

        public void DrawLine(Vector2 start, Vector2 end, Color color, int thickness)
        {
            float X = end.X - start.X;
            float Y = end.Y - start.Y;
            float Hyp = MathUtil.Hypotenuse(X, Y);

            Vector2 direction = new Vector2(X, Y);
            if (direction != Vector2.Zero)
            {
                direction.Normalize();
            }

            Rectangle rect = new Rectangle((int)start.X, (int)start.Y, (int)Hyp, thickness);
            float ang = Vector2Util.Angle(direction);

            DrawRectangle(rect, color, ang);
        }
    }
}
